#include "linux_timer.h"
#include <stdlib.h>

/* 系统滴答计数（模拟Linux的jiffies，从0开始递增） */
static jiffies_t jiffies = 0;

/* 定时器链表头（所有激活的定时器按expires升序排列，提高遍历效率） */
static linux_timer_t *timer_list = NULL;

/* 硬件滴答周期（毫秒，默认1ms，需与硬件定时器周期一致） */
#define TICK_MS 1

/* 初始化定时器模块 */
void linux_timer_init(void) {
    jiffies = 0;       /* 重置系统滴答计数 */
    timer_list = NULL; /* 清空定时器链表 */
}

/* 初始化单个定时器 */
void linux_timer_setup(linux_timer_t *timer, timer_func_t func, void *data,
                      bool periodic, uint32_t interval) {
    if (timer == NULL || func == NULL) return;

    timer->next = NULL;
    timer->expires = 0;
    timer->function = func;
    timer->data = data;
    timer->periodic = periodic;
    timer->interval = interval; /* 周期模式的间隔（滴答数） */
    timer->active = false;      /* 初始未激活 */
}

/* 将定时器按expires升序插入链表（核心：模拟Linux的有序链表） */
static void timer_insert(linux_timer_t *timer) {
    linux_timer_t **prev = &timer_list;

    /* 遍历链表，找到第一个expires >= 当前定时器expires的位置 */
    while (*prev != NULL && (*prev)->expires < timer->expires) {
        prev = &(*prev)->next;
    }

    /* 插入到链表中（prev指向插入位置的前一个节点的next指针） */
    timer->next = *prev;
    *prev = timer;
}

/* 启动定时器（计算超时滴答数并插入有序链表） */
void linux_timer_start(linux_timer_t *timer, uint32_t expires_ms) {
    if (timer == NULL || timer->active || expires_ms == 0) return;

    /* 计算超时滴答数：当前滴答数 + 毫秒转换的滴答数（向上取整） */
    jiffies_t expires_ticks = jiffies + (expires_ms + TICK_MS - 1) / TICK_MS;
    timer->expires = expires_ticks;

    /* 标记为激活并插入有序链表 */
    timer->active = true;
    timer_insert(timer);
}

/* 停止定时器（从链表中移除） */
void linux_timer_stop(linux_timer_t *timer) {
    if (timer == NULL || !timer->active) return;

    linux_timer_t **prev = &timer_list;

    /* 遍历链表找到要移除的定时器 */
    while (*prev != NULL && *prev != timer) {
        prev = &(*prev)->next;
    }

    /* 从链表中移除 */
    if (*prev != NULL) {
        *prev = timer->next; /* 跳过当前节点 */
    }

    timer->active = false;
    timer->next = NULL;
}

/* 定时器心跳函数（处理超时事件） */
void linux_timer_tick(void) {
    /* 递增系统滴答计数（模拟jiffies递增） */
    jiffies++;

    /* 处理所有已超时的定时器（链表按expires升序，只需检查头部） */
    while (timer_list != NULL && timer_list->expires <= jiffies) {
        linux_timer_t *timer = timer_list;

        /* 先从链表中移除（避免回调中操作链表导致冲突） */
        timer_list = timer->next;
        timer->active = false;

        /* 执行回调函数（类似Linux的timer->function(timer->data)） */
        if (timer->function != NULL) {
            timer->function(timer->data);
        }

        /* 周期模式：重新计算超时时间并插入链表 */
        if (timer->periodic) {
            timer->expires = jiffies + timer->interval;
            timer->active = true;
            timer_insert(timer); /* 重新插入链表（保持有序） */
        }
    }
}

/* 获取当前滴答数 */
jiffies_t linux_timer_get_jiffies(void) {
    return jiffies;
}